//#include "stdafx.h"
#include "Date.h"


Date::Date()
{
	day = 0;
	month = 0;
	year=0;
}

Date::Date(int day, int month, int year)
{
	day = day;
	month = month;
	year=year;
}

int Date::getDay()
{
	return day;
}
void Date::setDay(int day)
{
	this->day=day;
}
int Date::getMonth()
{
	return month;
}
void Date::setMonth(int month)
{
	this->month=month;
}
int Date::getYear()
{
	return year;
}
void Date::setYear(int year)
{
	this->year=year;
}
Event Date::getEvent(int eventIndex )
{
	return eventList[eventIndex];
}

int Date::getEventListLength()
{
	return eventList.size();
}

vector<Event> Date::getEventList()
{
	return eventList;
}
int Date::compareDates(Date obj)
{
	int date1,date2;
	date1=year*10000+month*100+day;
	date2=obj.year*10000+obj.month*100+obj.day;
	return date2-date1;
}
int Date::dateDifference(Date dateToCompare)
{
	Date temp;
	temp.setDay(getDay());
	temp.setMonth(getMonth());
	temp.setYear(getYear());
	
	int difference=0;
	if(temp.compareDates(dateToCompare)>=0)
	{
		while(temp.compareDates(dateToCompare)!=0)
		{
			temp.incrementDays(1);
			difference++;
		}
	}
	else
	{
		while(dateToCompare.compareDates(temp)!=0)
		{
			dateToCompare.incrementDays(1);
			difference++;
		}
	}

	return difference;
}
void Date::addEvent(string id, string name, string time, string location, Time startTime, Time endTime, string eventType, string eventStatus)
{
	int i=0;
	Event currentObject (id,name,time, location, startTime, endTime, eventType, eventStatus);
	for(i=0;i<eventList.size();i++)
	{
		if(currentObject.getStartTime().isGreaterThan(eventList[i].getStartTime()))
			continue;
		else break;
	}
	eventList.insert(eventList.begin()+i,currentObject);
	return;
}

void Date::deleteEvent(int deleteIndex)
{
	eventList.erase(eventList.begin() + deleteIndex);
}
void Date::editEvent(int editIndex, Task currentTask, Time startTime, Time endTime )
{

	if (currentTask.name!="")
	{
		eventList[editIndex].setName(currentTask.name);
	}

	if (currentTask.time!="")
	{
		eventList[editIndex].setTime(currentTask.time);
		eventList[editIndex].setStartTime(startTime);
		eventList[editIndex].setEndTime(endTime);
		Event tempObj=eventList[editIndex];
		deleteEvent(editIndex);
		addEvent(tempObj.getId(),tempObj.getName(),tempObj.getTime(),tempObj.getLocation(),tempObj.getStartTime(),tempObj.getEndTime(), tempObj.getEventType(), tempObj.getEventStatus());
	}

	if (currentTask.location!="")
	{
		eventList[editIndex].setLocation(currentTask.location);
	}


}
int Date::getIndex(string givenId)
{
	for (int i=0; i <eventList.size(); i++)
	{
		if (givenId==eventList[i].getId())
			return i;
	}
	return -1;
}
void Date::incrementDays(int noOfDays)
{
	int daysInMonths[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	if(isLeap())
		daysInMonths[2]+=1;
	for(int i=1;i<=noOfDays;i++)
	{
		day++;
		if(day > daysInMonths[month])
		{
			month++;
			if(month > 12)
			{
				year++;
				if(isLeap())
					daysInMonths[2]+=1;
				month=1;
			}
			day=1;
		}
	}
}

void Date::decrementDays(int noOfDays)
{
	int daysInMonths[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	if(isLeap())
		daysInMonths[2]+=1;
	for(int i=1;i<=noOfDays;i++)
	{
		day--;
		if(day < 0)//daysInMonths[month])
		{
			month--;
			if(month < 1)
			{
				year--;
				if(isLeap())
					daysInMonths[2]+=1;
				month=12;
			}
			day=daysInMonths[month];
		}
	}
}
bool Date::isLeap()
{
	if( year % 4==0 && year%100 !=0 || year % 400 ==0)
		return  true;
	return false;
}
string Date::getLargestId()
{
	string currentId = "", prevId = "";

	for (int i =0; i <getEventListLength(); i++)
	{
		currentId = getEvent(i).getId();
		if (currentId > prevId)
			prevId = currentId;
	}
	return prevId;
}

vector<string> Date::tokenize(string inputDate)
{
	stringstream strstr(inputDate);
	vector<string> tokenizedDate;
	string buffer;
	while(strstr >> buffer)
		tokenizedDate.push_back(buffer);
	return tokenizedDate;
}

bool Date::equalsIgnoreCase(string str1, string str2){
	
	if (str1.size() != str2.size()) 
		return false;
    for (string::const_iterator c1 = str1.begin(), c2 = str2.begin(); c1 != str1.end(); ++c1, ++c2){
        if (tolower(*c1) != tolower(*c2)) 
			return false;
    }
    return true;
}
vector<string> Date::removeSlash(string date)
{
	vector<string> dateWithoutSlash;
	char *pch;
	char *str;
	str = new char [date.size()+1];
	strcpy(str, date.c_str());

	pch = strtok(str,"/.");
	while(pch!=NULL)
	{
		dateWithoutSlash.push_back(pch);
		pch=strtok(NULL,"/.");
	}
	return dateWithoutSlash;
}
bool Date::hasSlashes(string date)
{
	int pos=date.find('/');
	int pos2=date.find('.');
	if(pos>-1 || pos2>-1)
		return true;
	return false;
}
Date Date:: setDateObject(int day, int month, int year)
{
	//assert(day>0);
	//assert(month>0);s
	//assert(year>0);
	Date dateObjectToBeReturned;
	dateObjectToBeReturned.setDay(day);
	dateObjectToBeReturned.setMonth(month);
	dateObjectToBeReturned.setYear(year);
	return dateObjectToBeReturned;
}
int Date::whichMonth(string month)
{
	string months[]={"january","february","march","april","may","june","july","august","september","october","november","december"};
	month=toLower(month);
	int i;
	for(i=0;i<12;i++)
	{
		if(months[i].compare(0,month.size(),month)==0)
			break;
	}
		
	return i+1;
}
string Date::toLower(string text)
{
	stringstream converted;
	for (int i=0; i<text.size();i++)
	{
		if (isdigit(text[i]))
			converted << text[i];
		else
			converted << (char)tolower(text[i]);
	}
	return converted.str();
}
bool Date::isMonth(string month)
{
	string months[]={"january","february","march","april","may","june","july","august","september","october","november","december"};
	month=toLower(month);
	bool flag=false;

	if(month.size()>=3)
	{
		for(int i=0;i<12;i++)
		{
			if(months[i].compare(0,month.size(),month)==0)
			{
				flag=true;
				break;
			}
		}
	}
	return flag;
}
bool Date::isValidDate(Date date)
{
	bool flag=true;
	if(date.getDay()<1)
		flag=false;
	if(date.getMonth()<1 || date.getMonth()> 12)
		flag=false;
	if(date.getYear()<2011 || date.getYear() > 2099)
		flag=false;
	int daysInMonths[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	if(date.isLeap())
		daysInMonths[2]+=1;
	if(date.getDay()>daysInMonths[date.getMonth()])
		flag=false;
	if(this->compareDates(date)<0)
		flag=false;
	return flag;
}

int Date::getCurrentDayIndex()
{
	time_t t=time(0);
	tm* now=localtime(&t);
	return now->tm_wday;
}

Date Date::dateStringToObject(string date)
{
	Date convertedDateObject;
	vector <string> tokenizedDate=tokenize(date);
	vector<string> dateWithoutSlash;
	int dayIndex=-1;
	int day=0;
	int month=0;
	int year=0;
	int currentDay = getCurrentDayIndex();
	string days[]={"sunday" , "monday","tuesday", "wednesday", "thursday", "friday", "saturday"}; 
	

	if(tokenizedDate.size()==1)
	{
		if(equalsIgnoreCase(date, "today"))
		{
			day = this->getDay();
			month = this->getMonth();
			year = this->getYear();
		}

		else if(equalsIgnoreCase(date, "tomorrow"))
		{
			Date nextDate=*this;
			nextDate.incrementDays(1);
			day = nextDate.getDay();
			month = nextDate.getMonth();
			year = nextDate.getYear();
		}
		
		else if(equalsIgnoreCase(date, days[1]))
		{
			dayIndex=1;
		}

		else if(equalsIgnoreCase(date, days[2]))
		{
			dayIndex=2;
		}
		else if(equalsIgnoreCase(date, days[3]))
		{
			dayIndex=3;
		}
		else if(equalsIgnoreCase(date, days[4]))
		{
			dayIndex=4;
		}
		else if(equalsIgnoreCase(date, days[5]))
		{
			dayIndex=5;
		}
		else if(equalsIgnoreCase(date, days[6]))
		{
			dayIndex=6;
		}
		else if(equalsIgnoreCase(date, days[0]))
		{
			dayIndex=0;
		}

		else if (hasSlashes(date))
		{
			dateWithoutSlash=removeSlash(date);
			
			if(dateWithoutSlash.size()==2)
			{
				day = atoi(dateWithoutSlash[0].c_str());
				month = atoi(dateWithoutSlash[1].c_str());
				year = this->getYear();
			}

			else if(dateWithoutSlash.size()==3)
			{
				//assuming input is in dd/mm/yyyy format only
				day=atoi(dateWithoutSlash[0].c_str());
				month=atoi(dateWithoutSlash[1].c_str());
				year= atoi(dateWithoutSlash[2].c_str());
			}
		}

		else if (date.size()==8)
		{
			day=atoi(date.substr(0,2).c_str());
			month=atoi(date.substr(2,2).c_str());
			year= atoi(date.substr(4,4).c_str());
		}

		if (dayIndex!=-1)
		{
			if (currentDay==dayIndex)
			{
				day = this->getDay();
				month = this->getMonth();
				year = this->getYear();
			}
			else if (currentDay < dayIndex)
			{
				Date nextDate=*this;
				nextDate.incrementDays(dayIndex-currentDay);
				day = nextDate.getDay();
				month = nextDate.getMonth();
				year = nextDate.getYear();
			}

			else 
			{
				Date nextDate=*this;
				nextDate.incrementDays(7+dayIndex-currentDay);
				day = nextDate.getDay();
				month = nextDate.getMonth();
				year = nextDate.getYear();
			}
		}
		convertedDateObject = setDateObject(day, month, year);
		//if(convertedDateObject.compareDates(*this)>0 && day!=0)
			//convertedDateObject.setYear(this->getYear()+1);
	}

	else if(tokenizedDate.size()>1 && tokenizedDate.size()<4)
	{
		//assuming input will be in the form of "September 29" or "29 September" or "29 September 2011" only
		if(isMonth(tokenizedDate[0]))
		{
			day=atoi(tokenizedDate[1].c_str());
			month=whichMonth(tokenizedDate[0]);
			year = this->getYear();
		}
		else if(isMonth(tokenizedDate[1]))
		{
			day=atoi(tokenizedDate[0].c_str());
			month=whichMonth(tokenizedDate[1]);
			year = this->getYear();
		}

		if (tokenizedDate.size()==3)
			year=atoi(tokenizedDate[2].c_str());

		convertedDateObject=setDateObject(day, month, year);
		//if(convertedDateObject.compareDates(*this)>0 && day!=0 && month !=0)
				//convertedDateObject.setYear(this->getYear()+1);

	}
	return convertedDateObject;
}


string Date::getEventDetails (int index)
{
	stringstream details;
	assert (index>=0 && index < eventList.size());
	Event eventObj = eventList[index];
	
	details << eventObj.getName();
	if (eventObj.getLocation() !="")
		details << " at " << eventObj.getLocation();
	details << " at "<< eventObj.getTime();
	details << ", ";
	details << getConvertedDate(eventObj.getId());
	details << endl;

	return details.str();
}

string Date::getConvertedDate(string tempDate)
{
	assert(tempDate!="");
	stringstream convertedDate ("");
	int day = atoi(tempDate.substr(0,2).c_str());//(tempDate.substr(0,2));
	if(day==0)
		throw "Date Not Valid";
	int month = atoi (tempDate.substr(2,2).c_str());
	if(month==0)
		throw "Month Not Valid";
	int year = atoi(tempDate.substr(4,4).c_str());
	if(year==0)
		throw "Year Not Valid";

	convertedDate<<day;
	if (day%10==1 && day!=11)
		convertedDate<<"st ";
	else if (day%10==2 && day!=12)
		convertedDate<<"nd ";
	else if (day%10==3 && day!=13)
		convertedDate<<"rd ";
	else 
		convertedDate<<"th ";

	string months[]={"January","February","March","April","May","June","July","August","September","October","November","December"};
	convertedDate<<months[month-1];
	convertedDate<<", ";
	convertedDate<<year;

	return convertedDate.str();
}

void Date::markEventAsDone(int markIndex)
{
	eventList[markIndex].setEventStatus("d");
}

void Date::markEventAsNotDone(int markIndex)
{
	eventList[markIndex].setEventStatus("nd");
}

Date::~Date(void)
{
}




